package com.hancheng.commoncloud.framework.util;

import cn.hutool.core.collection.CollUtil;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
public class BeanUtils {

    public static String[] getNullPropertyNames (Object source) {
        final BeanWrapper src = new BeanWrapperImpl(source);
        PropertyDescriptor[] pds = src.getPropertyDescriptors();

        Set<String> emptyNames = new HashSet<String>();

        for(PropertyDescriptor pd : pds) {
            Class aClass = src.getPropertyType(pd.getName());
            if (String.class.equals(aClass) || Date.class.equals(aClass) || Integer.class.equals(aClass)
                    || Long.class.equals(aClass) || BigDecimal.class.equals(aClass)){
                Object srcValue = src.getPropertyValue(pd.getName());

                if (srcValue == null) emptyNames.add(pd.getName());
            }else {
                emptyNames.add(pd.getName());
            }

        }
        String[] result = new String[emptyNames.size()];
        return emptyNames.toArray(result);
    }
    public static void copyPropertiesIgnoreNull(Object src, Object target){

        org.springframework.beans.BeanUtils.copyProperties(src, target, getNullPropertyNames(src));
    }

    public static <O, D> void copyCollectionProperties(Collection<O> org, Collection<D> dst, Class<D> clazz) {
        try {
            if (org == null || dst == null) {
                throw new NullPointerException("org or dst bean is null");
            }
            for (O o : org) {
                D d = clazz.newInstance();
                dst.add(d);
                copyPropertiesIgnoreNull(o, d);
            }
        } catch (Exception e) {
            log.error("Copy collection properties error", e);
        }
    }


    /**
     * 实体类转Map
     *
     * @param obj
     * @param prefix key前缀
     * @return
     */
    public static Map<String, String> entityToMap(Object obj, String prefix) {
        if (obj == null) {
            return null;
        }
        Map<String, String> map = Maps.newHashMap();
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor property : propertyDescriptors) {
                String key = property.getName();

                // 过滤class属性
                if (!"class".equals(key)) {
                    // 得到property对应的getter方法
                    Method getter = property.getReadMethod();
                    Object value = getter.invoke(obj);
                    if (value != null) {
                        map.put(prefix + key, String.valueOf(value));
                    }
                }
            }
        } catch (Exception e) {
            log.error("transBean2Map Error", e);
        }
        return map;
    }

    /**
     * 实体类转Map
     *
     * @param obj
     * @param prefix key前缀
     * @return
     */
    public static Map<String, Object> entityToMapObject(Object obj, String prefix) {
        if (obj == null) {
            return null;
        }
        Map<String, Object> map = Maps.newHashMap();
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor property : propertyDescriptors) {
                String key = property.getName();

                // 过滤class属性
                if (!"class".equals(key)) {
                    // 得到property对应的getter方法
                    Method getter = property.getReadMethod();
                    Object value = getter.invoke(obj);
                    if (value != null) {
                        map.put(prefix + key, String.valueOf(value));
                    }
                }
            }
        } catch (Exception e) {
            log.error("transBean2Map Error", e);
        }
        return map;
    }

    /**
     * list转换到成其它list
     * @param sourceList
     * @param target
     * @param <T>
     * @param <F>
     * @return
     */
    public static <T,F> List<F> listToOtherList(List<T> sourceList, Class<F> target) {
        List<F> targetList = new ArrayList<>();
        if(CollUtil.isNotEmpty(sourceList)) {
            targetList = sourceList.stream().map(e-> {
                F f = null;
                try {
                    f = target.newInstance();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
                org.springframework.beans.BeanUtils.copyProperties(e, f);
                return f;
            }).collect(Collectors.toList());
        }
        return targetList;
    }
}
